package org.mcache;

import org.mcache.cmd.Commands;

import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: tjc
 * @description
 * @Date Created in 11:06 2022-08-07
 */
public class RedisServer {
    RedisDb db;

    static RedisCommand commandTable[] = {
            // key
            new RedisCommand("get", Commands.get, 1),
            new RedisCommand("set", Commands.set, 2),
            new RedisCommand("del", Commands.del, 1),

            // string
            new RedisCommand("getrange", Commands.getrange, 3),
            new RedisCommand("getset", Commands.getset, 2),
            new RedisCommand("setnx", Commands.setnx, 2),
            new RedisCommand("mset", Commands.mset, 2),
            new RedisCommand("setex", Commands.setex, 3),
            new RedisCommand("decr", Commands.decr, 1),
            new RedisCommand("decrby", Commands.decrby, 2),
            new RedisCommand("strlen", Commands.strlen, 1),
            new RedisCommand("mget", Commands.mget, -1),
            new RedisCommand("incr", Commands.strlen, 1),

            // hash
            new RedisCommand("hget", Commands.hget, 2),
            new RedisCommand("hset", Commands.hset, 3),
            new RedisCommand("hdel", Commands.hdel, 2),
            new RedisCommand("hexists", Commands.hexists, 2),
            new RedisCommand("hincrby", Commands.hincrby, 3),
            new RedisCommand("hgetall", Commands.hgetall, 1),
            new RedisCommand("hmset", Commands.hmset, -3),
            new RedisCommand("hmget", Commands.hmget, -2),
            new RedisCommand("hlen", Commands.hlen, 1),
            new RedisCommand("hvals", Commands.hvals, 1),
            new RedisCommand("hincrbyfloat ", Commands.hincrbyfloat, 3),
            new RedisCommand("hkeys ", Commands.hkeys, 3),
            new RedisCommand("hsetnx ", Commands.hsetnx, 3),

            // list
            new RedisCommand("lset", Commands.lset, 3),
            new RedisCommand("lindex", Commands.lindex, 2),
            new RedisCommand("rpush", Commands.rpush, -2),
            new RedisCommand("lpush", Commands.rpush, -2),
            new RedisCommand("lrange", Commands.lrange, 3),
            new RedisCommand("rpoplpush", Commands.rpoplpush, 2),
            new RedisCommand("brpoplpush", Commands.brpoplpush, 3),
            new RedisCommand("blpop", Commands.blpop, 2),
            new RedisCommand("brpop", Commands.brpop, 2),
            new RedisCommand("lpop", Commands.lpop, 2),
            new RedisCommand("rpop", Commands.rpop, 2),
            new RedisCommand("linsert", Commands.linsert, 2),

            // set
            new RedisCommand("sadd", Commands.sadd, 2),
            new RedisCommand("spop", Commands.spop, 2),
            new RedisCommand("scard", Commands.scard, 2),
    };

    static Map<String, RedisCommand> cmdMap;

    static {
        cmdMap = Arrays.stream(commandTable).collect(Collectors.toMap(RedisCommand::getName, cmd -> cmd));
    }

    public void execute(RedisClient client) {
        RedisCommand cmd = cmdMap.get(client.getArg(0).value());
        if (cmd == null) {
            client.addReplyError("unsupported cmd");
            return;
        }

        client.setCmd(cmd);
        cmd.getProc().apply(client);
    }
}
